#pragma once


//-----------------------------------------------------------------------------
//																	Events
//-----------------------------------------------------------------------------

typedef enum EInputEvent
{
	eKey_Unknown,

	//	keyboard keys
	eKey_LShift,
	eKey_RShift,
	eKey_LCtrl,
	eKey_RCtrl,
	eKey_LAlt,
	eKey_RAlt,
	
	eKey_Esc,
	eKey_Tab,
	eKey_Backspace,
	eKey_Enter,
	eKey_Space,

	eKey_Insert,
	eKey_Delete,
	eKey_Home,
	eKey_End,
	eKey_PageDown,
	eKey_PageUp,

	eKey_NumLock,
	eKey_CapsLock,
	eKey_ScrollLock,
	eKey_Pause,

	eKey_Left,
	eKey_Right,
	eKey_Up,
	eKey_Down,

	eKey_Tilde,
	eKey_Dot,
	eKey_Comma,
	eKey_Minus,
	eKey_Plus,
	eKey_Semicolon,
	eKey_Quote,

	eKey_ForwardSlash,
	eKey_BackSlash,
	eKey_LBracket,
	eKey_RBracket,

	eKey_F1,
	eKey_F2,
	eKey_F3,
	eKey_F4,
	eKey_F5,
	eKey_F6,
	eKey_F7,
	eKey_F8,
	eKey_F9,
	eKey_F10,
	eKey_F11,
	eKey_F12,

	eKey_Num1,
	eKey_Num2,
	eKey_Num3,
	eKey_Num4,
	eKey_Num5,
	eKey_Num6,
	eKey_Num7,
	eKey_Num8,
	eKey_Num9,
	eKey_Num0,

	eKey_A,
	eKey_B,
	eKey_C,
	eKey_D,
	eKey_E,
	eKey_F,
	eKey_G,
	eKey_H,
	eKey_I,
	eKey_J,
	eKey_K,
	eKey_L,
	eKey_M,
	eKey_N,
	eKey_O,
	eKey_P,
	eKey_Q,
	eKey_R,
	eKey_S,
	eKey_T,
	eKey_U,
	eKey_V,
	eKey_W,
	eKey_X,
	eKey_Y,
	eKey_Z,

	//	mouse keys
	eKey_Mouse1,
	eKey_Mouse2,
	eKey_Mouse3,
	eKey_Mouse4,
	eKey_Mouse5,
	eKey_MouseWheel,
	eKey_MouseX,
	eKey_MouseY,

	eKey_Count
} EKey;

enum EKeyState
{
	eKeyState_Unknown,
	eKeyState_Pressed,
	eKeyState_Released
};

//-----------------------------------------------------------------------------
//															IInputListener
//-----------------------------------------------------------------------------

struct SInputEvent
{
	EInputEvent	event_type;
	EKeyState		key_state;
	bool				autorepeat;	//	event automatically repeated while holding the key
	char				character;	//	ascii character
	float				value;			//	valid for mouse wheel, mousex, mousey events

	//	modifiers keys
	bool				alt;
	bool				shift;
	bool				ctrl;
};

struct IInputListener
{
	virtual void OnInputEvent(const SInputEvent& input_event) = 0;
};

//-----------------------------------------------------------------------------
//																	Mouse
//-----------------------------------------------------------------------------

struct IMouse
{
	virtual void	IncrementCursor() = 0;
	virtual void	DecrementCursor() = 0;

	virtual void	SetPos(uint x, uint y) = 0;
	virtual Vec2i	GetPos() const = 0;
};

//-----------------------------------------------------------------------------
//																	Keyboard
//-----------------------------------------------------------------------------

struct IKeyboard
{
	virtual bool IsKeyPressed(EKey key) const = 0;
};

//-----------------------------------------------------------------------------
//																ActionManager
//-----------------------------------------------------------------------------

struct SActionEvent
{
public:
	explicit SActionEvent(const char* event_name): m_event(event_name) {}
	SActionEvent(const SActionEvent& action_event): m_event(action_event.m_event) {}

	bool operator== (const SActionEvent& rhs) const
	{
		return this->m_event == rhs.m_event;
	}

	bool operator!= (const SActionEvent& rhs) const
	{
		return !(*this == rhs);
	}

private:
	string m_event;
};

struct IActionListener
{
	virtual void OnActionEvent(const SActionEvent& action_event) = 0;
};

struct IActionManager
{
	virtual void RegisterListener(IActionListener* listener) = 0;
	virtual void UnregisterListener(IActionListener* listener) = 0;
};

//-----------------------------------------------------------------------------
//																		Input
//-----------------------------------------------------------------------------

struct IInput
{
	virtual ~IInput() {}

	virtual bool Init() = 0;
	virtual void Update() = 0;

	virtual void RegisterListener(IInputListener* listener) = 0;
	virtual void UnregisterListener(IInputListener* listener) = 0;

	//	AHTUNG! ->	Windows specific, should be refactored ASAP
	virtual void DispatchMessage(uint msg, WPARAM wParam, LPARAM lParam) = 0;

	virtual IMouse*					GetMouse() = 0;
	virtual IKeyboard*			GetKeyboard() = 0;
	virtual IActionManager*	GetActionManager() = 0;
};